package proyecto1IA;

import java.awt.Point;
import java.util.ArrayList;

public class Profundidad {

    private int matrizPosiciones[][];
    private Point robot, objeto1, objeto2, lugar1, lugar2;
    private ArrayList<ArrayList<Point>> solucion;
    private boolean encontradoObj1, encontradoObj2, entregadoLugar1, entregadoLugar2;
    private int profundidad;
    private int nodos;

    public Profundidad(int[][] matrizPosiciones, Point robot, Point objeto1, Point objeto2, Point lugar1, Point lugar2) {
        this.matrizPosiciones = matrizPosiciones;
        this.robot = robot;
        this.objeto1 = objeto1;
        this.objeto2 = objeto2;
        this.lugar1 = lugar1;
        this.lugar2 = lugar2;
        encontradoObj1 = false;
        encontradoObj2 = false;
        entregadoLugar1 = false;
        entregadoLugar2 = false;
        profundidad = 1;
        nodos = 1;
    }

    public ArrayList<ArrayList<Point>> controladorProfundidad() {

        //Recoge alguno de los 2 objetos
        solucion = new ArrayList<ArrayList<Point>>();
        solucion.add(buscarObjetos(robot, new ArrayList<Point>()));
        solucion.get(0).remove(solucion.get(0).size() - 1);

        //Si recogió el objeto 1 mira si puede entregarlo o ir por el otro objeto 2
        if (encontradoObj1) {
            imprimir("ENcontradoObj1");
            solucion.add(buscarObjetivos(robot, new ArrayList<Point>(), objeto2, lugar1));
            solucion.get(1).remove(solucion.get(1).size() - 1);
        } //Si recogió el 2 objeto mira si puede entregarlo o ir por el otro objeto 1
        else if (encontradoObj2) {
            imprimir("ENcontradoObj2");
            solucion.add(buscarObjetivos(robot, new ArrayList<Point>(), objeto1, lugar2));
            solucion.get(1).remove(solucion.get(1).size() - 1);
        }

        //Revisa si encontró un objeto o si lo entregó
        if (encontradoObj1 && entregadoLugar1) {
            imprimir("ENcontradosObj1 y EntregadoObj1");
            solucion.add(buscarObjetivos(robot, new ArrayList<Point>(), objeto2, objeto2));
            solucion.get(2).remove(solucion.get(2).size() - 1);

        } else if (encontradoObj2 && entregadoLugar2) {
            imprimir("ENcontradosObj2 y EntregadoObj2");
            solucion.add(buscarObjetivos(robot, new ArrayList<Point>(), objeto1, objeto1));
            solucion.get(2).remove(solucion.get(2).size() - 1);

        } else if (encontradoObj1 && encontradoObj2) {
            imprimir("ENcontradosObj1 y ENcontradoObj2");
            solucion.add(buscarObjetivos(robot, new ArrayList<Point>(), lugar1, lugar2));
            solucion.get(2).remove(solucion.get(2).size() - 1);
        }

        //Busca la última meta a la que levar el objeto restante
        if (entregadoLugar1) {
            imprimir("EntregadoObj1");
            solucion.add(buscarObjetivos(robot, new ArrayList<Point>(), lugar2, lugar2));
        } else if (entregadoLugar2) {
            imprimir("EntregadoObj2");
            solucion.add(buscarObjetivos(robot, new ArrayList<Point>(), lugar1, lugar1));
        }

        return solucion;
    }

    public ArrayList<Point> buscarObjetos(Point actual, ArrayList<Point> caminoRecorrido) {

        ArrayList<Point> temporal;
        if (!(actual.x < 0 || actual.y < 0 || actual.x == matrizPosiciones.length || actual.y == matrizPosiciones.length)) {
            if (!caminoRecorrido.contains(actual) || caminoRecorrido.isEmpty()) {
                if (!(actual.equals(objeto1) || actual.equals(objeto2))) {
                    caminoRecorrido.add(actual);

                    nodos++;
                    profundidad++;
                    //Arriba
                    temporal = buscarObjetos(new Point(actual.x - 1, actual.y), caminoRecorrido);
                    if (!temporal.isEmpty()) {
                        if (caminoRecorrido.get(caminoRecorrido.size() - 1).equals(objeto1)) {
                            encontradoObj1 = true;
                            robot = objeto1;
                        } else {
                            encontradoObj2 = true;
                            robot = objeto2;
                        }
                        return temporal;
                    }

                    nodos++;
                    profundidad++;
                    //Derecha
                    temporal = buscarObjetos(new Point(actual.x, actual.y + 1), caminoRecorrido);
                    if (!temporal.isEmpty()) {
                        if (caminoRecorrido.get(caminoRecorrido.size() - 1).equals(objeto1)) {
                            encontradoObj1 = true;
                            robot = objeto1;
                        } else {
                            encontradoObj2 = true;
                            robot = objeto2;
                        }
                        return temporal;
                    }

                    nodos++;
                    profundidad++;
                    //Abajo
                    temporal = buscarObjetos(new Point(actual.x + 1, actual.y), caminoRecorrido);
                    if (!temporal.isEmpty()) {
                        if (caminoRecorrido.get(caminoRecorrido.size() - 1).equals(objeto1)) {
                            encontradoObj1 = true;
                            robot = objeto1;
                        } else {
                            encontradoObj2 = true;
                            robot = objeto2;
                        }
                        return temporal;
                    }

                    nodos++;
                    profundidad++;
                    //Izquierda
                    temporal = buscarObjetos(new Point(actual.x, actual.y - 1), caminoRecorrido);
                    if (!temporal.isEmpty()) {
                        if (caminoRecorrido.get(caminoRecorrido.size() - 1).equals(objeto1)) {
                            encontradoObj1 = true;
                            robot = objeto1;
                        } else {
                            encontradoObj2 = true;
                            robot = objeto2;
                        }
                        return temporal;
                    } else {
                        caminoRecorrido.remove(caminoRecorrido.size() - 1);
                        
                    }
                } else {
                    caminoRecorrido.add(actual);
                    return caminoRecorrido;
                }
            }
            
        }
        nodos--;
        profundidad--;
        return new ArrayList();
    }

    public ArrayList<Point> buscarObjetivos(Point actual, ArrayList<Point> caminoRecorrido, Point objetivo1, Point objetivo2) {

        ArrayList<Point> temporal;

        if (!(actual.x < 0 || actual.y < 0 || actual.x == matrizPosiciones.length || actual.y == matrizPosiciones.length)) {
            if (!caminoRecorrido.contains(actual) || caminoRecorrido.isEmpty()) {
                if (!(actual.equals(objetivo1) || actual.equals(objetivo2))) {
                    caminoRecorrido.add(actual);

                    nodos++;
                    profundidad++;
                    //Arriba
                    temporal = buscarObjetivos(new Point(actual.x - 1, actual.y), caminoRecorrido, objetivo1, objetivo2);
                    if (!temporal.isEmpty()) {
                        if (caminoRecorrido.get(caminoRecorrido.size() - 1).equals(objetivo1)) {

                            if (objetivo1.equals(objeto1)) {
                                encontradoObj1 = true;
                                robot = objeto1;
                            }

                            if (objetivo1.equals(objeto2)) {
                                encontradoObj2 = true;
                                robot = objeto2;
                            }

                            if (objetivo1.equals(lugar1)) {
                                entregadoLugar1 = true;
                                robot = lugar1;
                            }

                            if (objetivo1.equals(lugar2)) {
                                entregadoLugar2 = true;
                                robot = lugar2;
                            }

                        } else if (caminoRecorrido.get(caminoRecorrido.size() - 1).equals(objetivo2)) {

                            if (objetivo2.equals(lugar1)) {
                                entregadoLugar1 = true;
                                robot = lugar1;
                            }

                            if (objetivo2.equals(lugar2)) {
                                entregadoLugar2 = true;
                                robot = lugar2;
                            }
                        }

                        return temporal;
                    }

                    nodos++;
                    profundidad++;
                    //Derecha
                    temporal = buscarObjetivos(new Point(actual.x, actual.y + 1), caminoRecorrido, objetivo1, objetivo2);
                    if (!temporal.isEmpty()) {
                        if (caminoRecorrido.get(caminoRecorrido.size() - 1).equals(objetivo1)) {

                            if (objetivo1.equals(objeto1)) {
                                encontradoObj1 = true;
                                robot = objeto1;
                            }

                            if (objetivo1.equals(objeto2)) {
                                encontradoObj2 = true;
                                robot = objeto2;
                            }

                            if (objetivo1.equals(lugar1)) {
                                entregadoLugar1 = true;
                                robot = lugar1;
                            }

                            if (objetivo1.equals(lugar2)) {
                                entregadoLugar2 = true;
                                robot = lugar2;
                            }

                        } else if (caminoRecorrido.get(caminoRecorrido.size() - 1).equals(objetivo2)) {

                            if (objetivo2.equals(lugar1)) {
                                entregadoLugar1 = true;
                                robot = lugar1;
                            }

                            if (objetivo2.equals(lugar2)) {
                                entregadoLugar2 = true;
                                robot = lugar2;
                            }
                        }
                        return temporal;
                    }

                    nodos++;
                    profundidad++;
                    //Abajo
                    temporal = buscarObjetivos(new Point(actual.x + 1, actual.y), caminoRecorrido, objetivo1, objetivo2);
                    if (!temporal.isEmpty()) {
                        if (caminoRecorrido.get(caminoRecorrido.size() - 1).equals(objetivo1)) {

                            if (objetivo1.equals(objeto1)) {
                                encontradoObj1 = true;
                                robot = objeto1;
                            }

                            if (objetivo1.equals(objeto2)) {
                                encontradoObj2 = true;
                                robot = objeto2;
                            }

                            if (objetivo1.equals(lugar1)) {
                                entregadoLugar1 = true;
                                robot = lugar1;
                            }

                            if (objetivo1.equals(lugar2)) {
                                entregadoLugar2 = true;
                                robot = lugar2;
                            }

                        } else if (caminoRecorrido.get(caminoRecorrido.size() - 1).equals(objetivo2)) {

                            if (objetivo2.equals(lugar1)) {
                                entregadoLugar1 = true;
                                robot = lugar1;
                            }

                            if (objetivo2.equals(lugar2)) {
                                entregadoLugar2 = true;
                                robot = lugar2;
                            }
                        }

                        return temporal;
                    }

                    nodos++;
                    profundidad++;
                    //Izquierda
                    temporal = buscarObjetivos(new Point(actual.x, actual.y - 1), caminoRecorrido, objetivo1, objetivo2);
                    if (!temporal.isEmpty()) {
                        if (caminoRecorrido.get(caminoRecorrido.size() - 1).equals(objetivo1)) {

                            if (objetivo1.equals(objeto1)) {
                                encontradoObj1 = true;
                                robot = objeto1;
                            }

                            if (objetivo1.equals(objeto2)) {
                                encontradoObj2 = true;
                                robot = objeto2;
                            }

                            if (objetivo1.equals(lugar1)) {
                                entregadoLugar1 = true;
                                robot = lugar1;
                            }

                            if (objetivo1.equals(lugar2)) {
                                entregadoLugar2 = true;
                                robot = lugar2;
                            }

                        } else if (caminoRecorrido.get(caminoRecorrido.size() - 1).equals(objetivo2)) {

                            if (objetivo2.equals(lugar1)) {
                                entregadoLugar1 = true;
                                robot = lugar1;
                            }

                            if (objetivo2.equals(lugar2)) {
                                entregadoLugar2 = true;
                                robot = lugar2;
                            }
                        }
                        return temporal;
                    } else {
                        caminoRecorrido.remove(caminoRecorrido.size() - 1);
                        
                    }
                } else {
                    caminoRecorrido.add(actual);
                    return caminoRecorrido;
                }
            }
            
        }
        nodos--;
        profundidad--;
        return new ArrayList();
    }

    public void imprimir(String mensaje) {
        System.out.println(mensaje);
    }

    public int getProfundidad() {
        return profundidad;
    }

    public int getNodos() {
        return nodos;
    }
}
